<!--
 * @Author: your name
 * @Date: 2021-04-07 22:11:13
 * @LastEditTime: 2021-04-08 20:48:14
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \JavaScript\05 - a为什么值时输出1.html
-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    // a为什么值时，会输出1
    // 两大类方法：利用转化为字符串重写toString方法、数据劫持

    // 方法1
    // 对象与原始类型比较时，对象会先转化成原始类型的值在进行比较
    // 对象转化为原始类型的值，先调用对象的valueOf方法，如果返回的还是对象，就会调用toString方法
    // 使用valueOf或者toString都可以
    // var a = {
    //   i: 0,
    //   toString() {
    //     return ++this.i
    //   }
    //   // valueOf() {
    //   //   return ++this.i
    //   // }
    // }

    // 方法2  数据劫持实现
    // 先举个栗子
    // let obj = {
    //   name: ''
    // }
    // Object.defineProperty(obj, 'name', {
    //   get() {
    //     console.log('获取');
    //   },
    //   set() {
    //     console.log('设置');
    //   }
    // })
    // obj.name = 'wsq' // 设置
    // obj.name // 获取
    // 解答
    // var i = 0
    // Object.defineProperty(window, 'a', {
    //   get() {
    //     return ++i
    //   }
    // })

    // ES6的proxy拦截代理
    var a = new Proxy({i: 0}, {
      get: (target, name) => {
        if (name === Symbol.toPrimitive) {
          return () => ++target.i
        } else {
          return target(name)
        }
      }
    })

    // 方法3
    // var a = [1, 2, 3]
    // a.join = a.shift
    // a.toString = a.shift // 每调用a都会触发toString方法，每次触发toString方法，都让他返回a.shift结果
    // shift()方法把数组的第一个元素删除，并且返回第一个元素
    // 函数带括号与不带括号的区别：函数只要是要调用它进行执行的，都必须加括号。
    // 此时，函数实际上等于函数的返回值或者执行效果，当然，有些没有返回值，
    // 但已经执行了函数体内的行为，就是说，加括号的，就代表将会执行函数体代码。
    // 不加括号的，都是把函数名称作为函数的指针，一个函数的名称就是这个函数的指针，
    // 此时不是得到函数的结果，因为不会运行函数体代码。
    // 它只是传递了函数体所在的地址位置，在需要的时候好找到函数体去执行。

    if (a == 1 && a == 2 && a == 3) {
      console.log('条件成立')
    }
  </script>
</body>
</html>